using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Wheels.Bing.RouteService;
using Wheels.Models;
using Wheels.TransitODataService;
using System.Configuration;
//using Wheels.TransitService;
//using PathStepObject = Wheels.TransitService.ItineraryLegObject;

namespace Wheels.Controllers
{
    [HandleError(View = "ErrorView")]
    public class TransitController : Controller
    {
        public const string IS_SHOW_TIME_KEY = "isShowTime";
        public const string STOP_NAME_KEY = "stopName";
        public const string EXEC_TYPE_KEY = "ExecType";
        public const string EXEC_TYPE_WHERE = "Where";
        public const string EXEC_TYPE_FASTEST = "Fastest";
        public const string EXEC_TYPE_NEXT = "Next";
        public const string BEST_PATHS = "BestPaths";


        public const String STOP_ID_KEY = "StationCode";
        public const String DESTINATION_STOP_ID_KEY = "DestinationCode";

        public static Dictionary<string, string> METRO_LINES_MAPPING = new Dictionary<string, string>
                                                                           {
                                                                               {"bl", "blue"},
                                                                               {"rd", "red"},
                                                                               {"yl", "yellow"},
                                                                               {"gr", "green"},
                                                                               {"or", "orange"}
                                                                           };

        private static TransitData data = null;
        public static TransitData Data
        {
            get
            {
                if (data == null)
                {
                    data = new TransitData(new Uri(ConfigurationManager.AppSettings["TransitODataServiceUri"]));
                }
                return data;
            }
        }

        public ActionResult LineInfo(string routeId, string stopId, string destinationCode)
        {
            Stop stop = Data.Stops.FirstOrDefault(s => s.StopId == stopId);
            Route route = Data.Routes.FirstOrDefault(r => r.RouteId == routeId);
            ViewData["stop"] = stop;

            return View(route);
            

            //using (var service = new TransitServiceClient())
            //{
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    LineObject[] lines =
            //        new TransitServiceClient().GetLinesByColor(METRO_LINES_MAPPING[color.ToLower()]).Items;
            //    Session.Add(DESTINATION_STOP_ID_KEY, destinationCode);
            //    ViewData["stop"] = stop;
            //    ViewData["route"] = color;

            //    return View(lines[0]);
            //}
        }

        public ActionResult SetMap(decimal Lat, decimal Lon, int Zoom, int Width, int Height)
        {
            Session["map_height"] = Height;
            Session["map_width"] = Width;

            AreaState area = GetCurrrentAreaOrDefault();
            area.Lat = Lat;
            area.Lon = Lon;
            area.Zoom = Zoom;
            area.Radius = (decimal) MapCreator.Radius(Zoom, Height, Width);

            if (area.CurrentLon == 38.8667590000M)
            {
                area.CurrentLat = Lat;
                area.CurrentLon = Lon;
            }

            return JsonGet(String.Empty);
        }

        private JsonResult JsonGet(object o)
        {
            return Json(o, JsonRequestBehavior.AllowGet);
        }

        public ActionResult SetCurrentPosition(decimal Lat, decimal Lon)
        {
            AreaState area = GetCurrrentAreaOrDefault();
            area.CurrentLat = Lat;
            area.CurrentLon = Lon;

            return JsonGet("set");
        }

        public AreaState GetCurrrentAreaOrDefault()
        {
            var area = Session["area"] as AreaState;

            if (area == null)
            {
                area = new AreaState
                           {
                               Lat = (decimal) 38.8667590000,
                               Lon = (decimal) -77.0541610000,
                               CurrentLat = (decimal) 38.8667590000,
                               CurrentLon = (decimal) -77.0541610000,
                               Zoom = 13,
                               Radius = (decimal) MapCreator.Radius(13, Client.MapWidth, Client.MapHeight)
                           };

                Session["area"] = area;
            }

            return area;
        }

        public ActionResult Map()
        {
            return View(Client);
        }


        public ActionResult TrainPredictions(string stopId)
        {
            if (String.IsNullOrEmpty(stopId))
            {
                stopId = Session[STOP_ID_KEY].ToString();
            }
            else
            {
                Session.Add(STOP_ID_KEY, stopId);
            }
            
            ViewData.Model = Data.GetStop(stopId, true, false, false);

            //using (var service = new TransitServiceClient())
            //{
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Add("stop", stop);
            //    ViewData.Model = service.GetStationPredictions(stopId, null).Items;
            //}

            return View("Trains");
        }

        public ActionResult BusStops()
        {
            AreaState area = GetCurrrentAreaOrDefault();

            ViewData.Model = Data.GetStopsAround(area.Lat, area.Lon, area.Radius).Where(s => s.Type == "Bus");
            //ViewData.Model = new TransitServiceClient().GetStops(area.Lat, area.Lon, area.Radius, 1, "bus", 0).Items;
            return View("BusStops");
        }

        public ActionResult BusStopAddRoute(string stopId)
        {
            
            ViewData.Model = Data.GetStop(stopId,false,false,true);            
            var result = new MyTripData(Request);
            ViewData.Add("favorite", result);

            //using (var service = new TransitServiceClient())
            //{
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Model = service.GetRoutes(stopId).Items;
            //    ViewData.Add("stop", stop);
            //    var result = new MyTripData(Request);
            //    ViewData.Add("favorite", result);
            //}

            return View();
        }

        public ActionResult SetSession(string key, string value)
        {
            Session[key] = value;
            return Json(string.Empty);
        }

        private void GetLatLon(string input, out decimal lat, out decimal lon)
        {
            string[] arr = input.Split('_');
            lat = decimal.Parse(arr[0].Replace(',', '.'), CultureInfo.InvariantCulture);
            lon = decimal.Parse(arr[1].Replace(',', '.'), CultureInfo.InvariantCulture);
        }

        public ActionResult SetStartTime()
        {
            return View();
        }

        public ActionResult ShowPath(string index)
        {
            ///TODO

            return JsonGet(null);

            //var ways = (ItineraryLegObject[][]) Session[BEST_PATHS];
            //return JsonGet(ways[int.Parse(index)]);
        }

        public ActionResult ComputePath(bool isPoints)
        {

            object startTime = Session["StartTime"];
            DateTime time;
            if (startTime == null)
            {
                //throw new Exception("Start Time is not set!");
                // TODO: for debug, delete and uncomment
                time = DateTime.Parse("09.08.2010 14:00:00");
            }
            else
            {
                if (!DateTime.TryParse(startTime.ToString(), out time))
                {
                    throw new Exception("Start Time is not correct!");
                }
            }

                List<Itinerary> itineraries = null;

                try
                {

                    if (!isPoints)
                    {
                        object startStopId = Session["startStop"];
                        object finishStopId = Session["finishStop"];
                        if ((startStopId == null) || (finishStopId == null))
                        {
                            throw new Exception("Start or Finish stops are not set!");
                        }

                        itineraries = Data.CalculateItineraryByStops(startStopId.ToString(), finishStopId.ToString(), time);
                    }
                    else
                    {
                        object startPoint = Session["startPoint"];
                        object finishPoint = Session["finishPoint"];
                        if ((startPoint == null) || (finishPoint == null))
                        {
                            throw new Exception("Start or Finish points are not set!");
                        }
                        decimal startLat, startLon, finishLat, finishLon;
                        GetLatLon(startPoint.ToString(), out startLat, out startLon);
                        GetLatLon(finishPoint.ToString(), out finishLat, out finishLon);

                        itineraries = Data.CalculateItineraryByPoints((double)startLat, (double)startLon, (double)finishLat, (double)finishLon, time);
                    }
                }
                catch (Exception ex)
                {
                    ViewData.Add("message", ex.Message);
                }

            Session[BEST_PATHS] = itineraries;
            ViewData.Model = itineraries;
            return View();            


            //ItineraryLegObject[][] ways = null;

            //using (var service = new TransitServiceClient())
            //{
            //    object startTime = Session["StartTime"];
            //    DateTime time;
            //    if (startTime == null)
            //    {
            //        //throw new Exception("Start Time is not set!");
            //        // TODO: for debug, delete and uncomment
            //        time = DateTime.Parse("09.08.2010 14:00:00");
            //    }
            //    else
            //    {
            //        if (!DateTime.TryParse(startTime.ToString(), out time))
            //        {
            //            throw new Exception("Start Time is not correct!");
            //        }
            //    }

            //    try
            //    {
            //        int k = 0;

            //        if (!isPoints)
            //        {
            //            object startStopId = Session["startStop"];
            //            object finishStopId = Session["finishStop"];
            //            if ((startStopId == null) || (finishStopId == null))
            //            {
            //                throw new Exception("Start or Finish stops are not set!");
            //            }

            //            ItineraryObject[] paths =
            //                service.ComputeItineraryStops(startStopId.ToString(), finishStopId.ToString(), time, 100).
            //                    Items;

            //            ways = new ItineraryLegObject[paths.Count()][];

            //            foreach (ItineraryObject pathObject in paths)
            //            {
            //                int j = 0;
            //                ways[k] = new ItineraryLegObject[pathObject.Legs.Count()];
            //                foreach (ItineraryLegObject step in pathObject.Legs)
            //                    ways[k][j++] = step;
            //                ++k;
            //            }
            //        }
            //        else
            //        {
            //            object startPoint = Session["startPoint"];
            //            object finishPoint = Session["finishPoint"];
            //            if ((startPoint == null) || (finishPoint == null))
            //            {
            //                throw new Exception("Start or Finish points are not set!");
            //            }
            //            decimal startLat, startLon, finishLat, finishLon;
            //            GetLatLon(startPoint.ToString(), out startLat, out startLon);
            //            GetLatLon(finishPoint.ToString(), out finishLat, out finishLon);

            //            ItineraryObject[] paths =
            //                service.ComputeItineraryPoints(startLat, startLon, finishLat, finishLon, time, 100).Items;

            //            ways = new ItineraryLegObject[paths.Count()][];

            //            foreach (ItineraryObject pathObject in paths)
            //            {
            //                int j = 0;
            //                ways[k] = new ItineraryLegObject[pathObject.Legs.Count()];
            //                foreach (ItineraryLegObject step in pathObject.Legs)
            //                    ways[k][j++] = step;
            //                ++k;
            //            }
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        ViewData.Add("message", ex.Message);
            //    }
            //}

            //Session[BEST_PATHS] = ways;
            //ViewData.Model = ways;
            //return View();
        }

        // for history
        //public ActionResult ShowPath(string index)
        //{
        //    Way[] ways = (Way[])Session[BEST_PATHS];
        //    return JsonGet(ways[int.Parse(index)].Steps);
        //}

        //public ActionResult ComputePath(bool isPoints)
        //{
        //    Way[] ways = null;

        //    using (BackendService.CleverServiceClient service = new BackendService.CleverServiceClient())
        //    {
        //        DateTime time = DateTime.Parse("01.01.1753 14:00:00");
        //        try
        //        {
        //            if (!isPoints)
        //            {
        //                object startStopId = Session["startStop"];
        //                object finishStopId = Session["finishStop"];
        //                if ((startStopId == null) || (finishStopId == null))
        //                {
        //                    throw new Exception("Start or Finish stops are not set!");
        //                }
        //                ways = service.ComputePathStops(startStopId.ToString(), finishStopId.ToString(), time, 100);
        //            }
        //            else
        //            {
        //                object startPoint = Session["startPoint"];
        //                object finishPoint = Session["finishPoint"];
        //                if ((startPoint == null) || (finishPoint == null))
        //                {
        //                    throw new Exception("Start or Finish points are not set!");
        //                }
        //                decimal startLat, startLon, finishLat, finishLon;
        //                GetLatLon(startPoint.ToString(), out startLat, out startLon);
        //                GetLatLon(finishPoint.ToString(), out finishLat, out finishLon);
        //                ways = service.ComputePathPoints(startLat, startLon,finishLat,finishLon, time, 100);
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            ViewData.Add("message", ex.Message);
        //        }
        //    }

        //    Session[BEST_PATHS] = ways;
        //    ViewData.Model = ways;
        //    return View();
        //}


        //private static List<LineData> _cachedLines;
        //private static object lockLineData = new Object();

        //public static List<LineData> CachedLines
        //{
        //    get
        //    {
        //        lock (lockLineData)
        //        {

        //        if (_cachedLines == null)
        //        {
        //                List<LineData> lines = new List<LineData>();
        //                using (BackendService.CleverServiceClient service = new CleverServiceClient())
        //                {
        //                    lines.AddRange(service.Lines("Red"));
        //                    lines.AddRange(service.Lines("Blue"));
        //                    lines.AddRange(service.Lines("Green"));
        //                    lines.AddRange(service.Lines("Orange"));
        //                    lines.AddRange(service.Lines("Yellow"));
        //                }
        //                _cachedLines = lines;
        //        }
        //        return _cachedLines;
        //        }                                        
        //    }
        //}

        //public IEnumerable<LineData> GetStationLines(string stationCode)
        //{            
        //    return CachedLines.Where(line => line.Stations.Any( s => s.Code == stationCode));
        //}

        public ActionResult TrainStop(string stopId)
        {
            ViewData.Model = Data.GetStop(stopId,false,false,true);

            //using (var service = new TransitServiceClient())
            //{
            //    ViewData.Model = service.GetStationLines(stopId).Items;
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Add("stop", stop);
            //}

            return View();
        }

        public ActionResult TrainStopAddRoute(string stopId)
        {
            ViewData.Model = Data.GetStop(stopId, false, false, true);
            var result = new MyTripData(Request);                        
            ViewData.Add("favorite", result);

            // the same train predictions
            //using (var service = new TransitServiceClient())
            //{
            //    ViewData.Model = service.GetStationLines(stopId).Items;

            //    var result = new MyTripData(Request);
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Add("stop", stop);
            //    ViewData.Add("favorite", result);
            //    //ViewData.Model = service.StationPredictions(stopId, null);
            //}

            return View();
        }

        public ActionResult TrainStops()
        {
            AreaState area = GetCurrrentAreaOrDefault();

            ViewData.Model = Data.GetStopsAround(area.Lat, area.Lon, area.Radius).Where(s => s.Type == "MetroTrain");

            //ViewData.Model = 
            //    new TransitServiceClient().GetStops(area.Lat, area.Lon, area.Radius, 1, "train", 0).Items;
            return View("TrainStops");
        }

        public JsonResult AreaStopsJSON(decimal Lat, decimal Lon, int Zoom, int Width, int Height)
        {
            AreaState area = GetCurrrentAreaOrDefault();
            area.Lat = Lat;
            area.Lon = Lon;
            area.Zoom = Zoom;
            area.Radius = (decimal)MapCreator.Radius(Zoom, Height, Width);

            IEnumerable<Stop> stops = Data.GetStopsInArea(area.Lat - area.Radius, area.Lon - area.Radius, area.Lat + area.Radius, area.Lon + area.Radius);

            var result = stops.Select(s => new { s.StopId, s.Lat, s.Lon, s.Type }).ToList();            
            //StopObject[] list = new TransitServiceClient().GetStops(Lat, Lon, area.Radius, 0, null, 0).Items;
            //var result = list.Select(i => new {i.StopID, i.Lat, i.Lon, i.Type}).ToList();
            return JsonGet(result);
        }

        public JsonResult AreaBusesJSON(decimal Lat, decimal Lon, int Zoom, int Width, int Height)
        {
            AreaState area = GetCurrrentAreaOrDefault();
            area.Lat = Lat;
            area.Lon = Lon;
            area.Zoom = Zoom;
            area.Radius = (decimal) MapCreator.Radius(Zoom, Height, Width);

            /// TODO: add buses

            //var list = new BusObject[0];
            //using (var service = new TransitServiceClient())
            //{
            //    list = service.GetAreaBuses(Lat, Lon, area.Radius).Items;
            //}

            return JsonGet(null);
        }    

        public ActionResult RouteInfo(string RouteId, string TripId, string stopId)
        {
            /// TODO:

            //ViewData.Model = Data.RoutesFirstOrDefault.GetTripInfo(TripId, stopId, null, false, true).Items;
            //ViewData.Model = new TransitServiceClient().GetTripInfo(TripId, stopId, null, false, true).Items;            

            return View();
        }

        public ActionResult ActionMenu()
        {
            return View();
        }

        public ActionResult BusStop(string stopId)
        {            
            ViewData.Model = Data.GetStop(stopId, false, false, true);            

            //using (var service = new TransitServiceClient())
            //{
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Model = service.GetRoutes(stopId).Items;
            //    ViewData.Add("stop", stop);
            //}

            return View();
        }

        public ActionResult BusRoute(string stopId, string routeId)
        {
            Route route = Data.Routes.Where(r => r.RouteId == routeId).FirstOrDefault();
            ViewData.Add("route", route);
            ViewData.Model = Data.GetStop(stopId, true ,true, false);               

            //ViewData.Model = Data.GetArrivalsByStop(stopId, int.MaxValue, true, true, null, null).Where(a => a.RouteId == routeId).ToList();               

            //using (var service = new TransitServiceClient())
            //{
            //    // If stopId is not empty get stop Name
            //    if (!string.IsNullOrEmpty(stopId))
            //    {
            //        ViewData.Add(STOP_NAME_KEY, service.GetStop(stopId, 0).Items.FirstOrDefault().Name);
            //    }

            //    // Go from BusStop page
            //    if (string.IsNullOrEmpty(tripId))
            //    {
            //        RouteObject route =
            //            service.GetRoutes(stopId).Items.Where(r => r.RouteID == routeId).FirstOrDefault();
            //        string _tripId = (directionOnStop == "0") ? route.ExampleTrip0ID : route.ExampleTrip1ID;
            //        ViewData.Model = service.GetTripInfo(_tripId, stopId, null, false, true).Items.First();
            //        ViewData.Add(IS_SHOW_TIME_KEY, false);
            //    }
            //    else //Go from Arrivals page. Need to show arrival time.
            //    {
            //        ViewData.Model = service.GetTripInfo(tripId, stopId, null, false, true).Items.First();
            //        ViewData.Add(IS_SHOW_TIME_KEY, true);
            //    }
            //}

            return View();
        }

        public ActionResult StopArrivals(string stopId)
        {
            if (String.IsNullOrEmpty(stopId))
            {
                stopId = Session[STOP_ID_KEY].ToString();
            }
            else
            {
                Session.Add(STOP_ID_KEY, stopId);
            }

            Stop stop = Data.Stops.Where(s => s.StopId == stopId).FirstOrDefault();
            ViewData.Model = Data.GetStop(stopId, true, false, false);
            

            

            //using (var service = new TransitServiceClient())
            //{
            //    StopObject stop = service.GetStop(stopId, 0).Items.FirstOrDefault();
            //    ViewData.Model = service.GetBusArrivalsByStops(stopId, DateTime.Now, DateTime.Now.AddHours(2)).Items;
            //    ViewData.Add("stop", stop);
            //}

            return View("StopArrivals");
        }

        public ActionResult BusStopShortInfo(string stopId, decimal lat, decimal lon)
        {
            AreaState area = GetCurrrentAreaOrDefault();

            Stop stop = Data.Stops.Where(s => s.StopId == stopId).FirstOrDefault();


            if (stop != null)
            {
                RouteResponse route = GetRoute(new GeographyPoint(area.CurrentLat, area.CurrentLon),
                                               new GeographyPoint(lat, lon));
                Session.Add("PedestrianRoute", route);
            }
            return View(stop);

                        
            //AreaState area = GetCurrrentAreaOrDefault();
            //StopObject stop = new TransitServiceClient().GetStops(lat, lon, 0, 0, "bus", 1).Items.FirstOrDefault();


            //if (stop != null)
            //{
            //    RouteResponse route = GetRoute(new GeographyPoint(area.CurrentLat, area.CurrentLon),
            //                                   new GeographyPoint(lat, lon));
            //    Session.Add("PedestrianRoute", route);
            //}
            //return View(stop);
        }

        public ActionResult TrainStopShortInfo(String stopId, decimal lat, decimal lon)
        {

            /// TODO:

            return View();

            //AreaState area = GetCurrrentAreaOrDefault();
            //StopObject stop = new TransitServiceClient().GetStops(lat, lon, 0, 0, "train", 1).Items.FirstOrDefault();

            //if (stop != null)
            //{
            //    Session.Add("StopInfo", stop);
            //    RouteResponse route = GetRoute(new GeographyPoint(area.CurrentLat, area.CurrentLon),
            //                                   new GeographyPoint(lat, lon));
            //    Session.Add("PedestrianRoute", route);
            //}

            //return View(stop);
        }

        public ActionResult BusShotInfo(String busId, String tripId, decimal lat, decimal lon)
        {

            /// TODO:

            return View();

            //var bus = new BusObject();
            //using (var service = new TransitServiceClient())
            //{
            //    BusObject list = service.GetBus(busId).Items.FirstOrDefault();
            //}

            //return View(bus);
        }


        public ActionResult RouteMap(string key, string tripId, string stopId)
        {
            /// TODO:

            return View();

            //ResultSetOfTripObject shapes = new TransitServiceClient().GetTripInfo(tripId, stopId, null, true, false);

            //AreaState area = GetCurrrentAreaOrDefault();
            //area.Route = new List<GeographyPoint>();
            //foreach (TripObject shape in shapes.Items)
            //    foreach (ShapePointObject shapepoint in shape.ShapePoints)
            //        area.Route.Add(new GeographyPoint(shapepoint.Lat, shapepoint.Lon));

            //return View("Map", Client);
        }

        public ActionResult GetBusRouteJSON(string tripId, string stopId)
        {
            /// TODO:

            return View();

            //ResultSetOfTripObject shapes = new TransitServiceClient().GetTripInfo(tripId, stopId, null, true, false);

            //AreaState area = GetCurrrentAreaOrDefault();
            //area.Route = new List<GeographyPoint>();
            //foreach (TripObject shape in shapes.Items)
            //    foreach (ShapePointObject shapepoint in shape.ShapePoints)
            //        area.Route.Add(new GeographyPoint(shapepoint.Lat, shapepoint.Lon));

            //return JsonGet(area.Route);
        }

        public ActionResult GetTrainRouteJSON(string color)
        {
            /// TODO:

            return View();

            //ResultSetOfLineObject shapes = new TransitServiceClient().GetLinesByColor(color);

            //AreaState area = GetCurrrentAreaOrDefault();
            //area.Route = new List<GeographyPoint>();
            //foreach (LineObject shape in shapes.Items)
            //    foreach (StopObject shapepoint in shape.Stations)
            //        area.Route.Add(new GeographyPoint(shapepoint.Lat, shapepoint.Lon));
            //return JsonGet(area.Route);
        }

        public ActionResult AddToFavarite(string stopId, string routeName, string directionID, string type)
        {
            var favorites = new FavoriteEntries(Request);
            var entry = new FavoriteEntry(stopId, routeName, directionID, type);
            if (!favorites.Contains(entry))
            {
                favorites.Add(entry);
                favorites.Save(Response);
            }

            return JsonGet("success");
        }

        public ActionResult RemoveFavarite(string stopId, string routeName, string directionID, string type)
        {
            var favorites = new FavoriteEntries(Request);
            var entry = new FavoriteEntry(stopId, routeName, directionID, type);
            if (favorites.Contains(entry))
            {
                favorites.Remove(entry);
                favorites.Save(Response);
            }

            return JsonGet("success");
        }

        public ActionResult SetExecType(string execType)
        {
            Session[EXEC_TYPE_KEY] = execType;

            return JsonGet("success");
        }

        public ActionResult MyTrip()
        {

            //var service = new TransitServiceClient();
            var result = new MyTripData(Request);
            List<TransitODataService.Arrival> allArivals = new List<TransitODataService.Arrival>();            

            foreach (var byStopId in result.Favorites.GroupBy(c => c.StopId))
            {
                Stop stop = Data.GetStop(byStopId.Key,true,false,false);
                result.Stops.Add(stop);
                
                foreach (TransitODataService.Arrival arrival in stop.Arrivals)
                {
                    if (result.Favorites.Contains(new FavoriteEntry(byStopId.Key, arrival.RouteName,
                                                                    arrival.DestinationStopId, stop.Type)))
                    {
                        allArivals.Add(arrival);
                    }
                }                
            }

            return View(result);

            //var service = new TransitServiceClient();
            //var result = new MyTripData(Request);
            //List<NearestArrivalObject> busArrivals;
            //List<MetroStationPredictionObject> trainArrivals;

            //foreach (var byStopId in result.Favorites.GroupBy(c => c.StopId))
            //{
            //    StopObject stop = service.GetStop(byStopId.Key, 0).Items.FirstOrDefault();
            //    result.Stops.Add(stop);

            //    if (String.Compare(stop.Type, "bus", true) == 0)
            //    {
            //        busArrivals = new List<NearestArrivalObject>();
            //        foreach (NearestArrivalObject arrival in stop.NearestArrivals)
            //        {
            //            if (
            //                result.Favorites.Contains(new FavoriteEntry(byStopId.Key, arrival.RouteName,
            //                                                            arrival.Direction.ToString(), "bus")))
            //                busArrivals.Add(arrival);
            //        }
            //        stop.NearestArrivals = busArrivals.ToArray();
            //    }
            //    else if (String.Compare(stop.Type, "train", true) == 0)
            //    {
            //        trainArrivals = new List<MetroStationPredictionObject>();
            //        foreach (MetroStationPredictionObject arrival in stop.NearestTrainArrivals)
            //        {
            //            if (
            //                result.Favorites.Contains(new FavoriteEntry(byStopId.Key, arrival.Line,
            //                                                            arrival.DestinationCode, "train")))
            //                trainArrivals.Add(arrival);
            //        }
            //        stop.NearestTrainArrivals = trainArrivals.ToArray();
            //    }
            //}

            //return View(result);
        }

        public static RouteResponse GetRoute(GeographyPoint location1, GeographyPoint location2)
        {
            var routeService = new RouteServiceClient();
            var routeRequest = new RouteRequest();

            routeRequest.Credentials = new Credentials();
            routeRequest.Credentials.ApplicationId = Settings.BingMapsApiKey;

            var wayPoints = new Waypoint[2];
            wayPoints[0] = new Waypoint();
            wayPoints[0].Location = new Location();
            wayPoints[0].Location.Latitude = (double) location1.Latitude;
            wayPoints[0].Location.Longitude = (double) location1.Longitude;
            wayPoints[1] = new Waypoint();
            wayPoints[1].Location = new Location();
            wayPoints[1].Location.Latitude = (double) location2.Latitude;
            wayPoints[1].Location.Longitude = (double) location2.Longitude;

            routeRequest.Waypoints = wayPoints;
            routeRequest.Options = new RouteOptions();
            routeRequest.Options.Optimization = RouteOptimization.MinimizeDistance;
            routeRequest.Options.RoutePathType = RoutePathType.Points;
            routeRequest.Options.Mode = TravelMode.Walking;

            routeRequest.UserProfile = new UserProfile();
            routeRequest.UserProfile.DistanceUnit = DistanceUnit.Mile;


            RouteResponse routeResponse;
            try
            {
                routeResponse = routeService.CalculateRoute(routeRequest);
            }
            catch // Any exception of calculation route
            {
                return null;
            }


            if (routeResponse.Result != null)
            {
                return routeResponse;
            }

            return null;
        }
    }

    public class FavoriteEntry
    {
        /// <summary>
        /// 'Direction' for 'bus' type and 'Destination Station' for 'train'
        /// </summary>
        public string DirectionID;

        /// <summary>
        /// 'Route Name' for 'bus' type and 'Line' for 'train'
        /// </summary>
        public string RouteName;

        /// <summary>
        /// Stop identity 
        /// </summary>
        public string StopId;

        /// <summary>
        /// 'bus' or 'train'
        /// </summary>
        public string Type;

        public FavoriteEntry(string stopId, string routeName, string directionID, string type)
        {
            StopId = stopId;
            RouteName = routeName;
            DirectionID = directionID;
            Type = type;
        }

        public static FavoriteEntry parse(string value)
        {
            string[] values = value.Split('/');
            if (values.Length == 4)
            {
                return new FavoriteEntry(values[0], values[1], values[2], values[3]);
            }
            return null;
        }

        public override string ToString()
        {
            var builder = new StringBuilder();
            builder.Append(StopId).Append('/')
                .Append(RouteName).Append('/')
                .Append(DirectionID).Append('/')
                .Append(Type);

            return builder.ToString();
        }

        public override bool Equals(object obj)
        {
            if (obj.GetType().Equals(typeof (FavoriteEntry)))
            {
                var entry = (FavoriteEntry) obj;
                return entry.StopId.Equals(StopId) &&
                       entry.RouteName.Equals(RouteName) &&
                       entry.DirectionID.Equals(DirectionID) &&
                       entry.Type.Equals(Type);
            }

            return false;
        }
    }

    public class FavoriteEntries : List<FavoriteEntry>
    {
        public FavoriteEntries(HttpRequestBase request)
        {
            HttpCookie cookie = request.Cookies["Favorites"];
            if (cookie != null && !String.IsNullOrEmpty(cookie.Value))
            {
                string[] entries = cookie.Value.Split('|');
                foreach (string entry in entries)
                {
                    FavoriteEntry favoriteEntry = FavoriteEntry.parse(entry);
                    if (favoriteEntry != null)
                    {
                        Add(favoriteEntry);
                    }
                }
            }
        }

        public override string ToString()
        {
            var builder = new StringBuilder();
            for (int i = 0; i < this.Count(); i++)
            {
                if (i > 0)
                {
                    builder.Append("|");
                }
                builder.Append(this[i].ToString());
            }
            return builder.ToString();
        }

        public void Save(HttpResponseBase response)
        {
            var cookie = new HttpCookie("Favorites");
            cookie.Expires = DateTime.Now.AddDays(30d);
            cookie.Value = ToString();
            response.SetCookie(cookie);
        }
    }
}